# -*- coding: utf-8 -*-
"""
MySQL客户端SQL脚本执行器 - Python 2.7.5版本
通过调用系统的mysql客户端命令执行SQL脚本
逐行执行SQL文件中的语句，每执行一个SQL后暂停1分钟
"""

import subprocess
import time
import sys
import os
import codecs
import tempfile
from datetime import datetime


def read_sql_file(file_path):
    """
    读取SQL文件并返回有效的SQL语句列表

    Args:
        file_path (str): SQL文件路径

    Returns:
        list: SQL语句列表，每个元素为(行号, SQL语句)
    """
    sql_statements = []

    if not os.path.exists(file_path):
        print("[%s] 错误: SQL文件不存在: %s" % (
            datetime.now().strftime('%Y-%m-%d %H:%M:%S'), file_path
        ))
        return sql_statements

    try:
        # 使用codecs.open来处理UTF-8编码，兼容Python 2.7
        with codecs.open(file_path, 'r', encoding='utf-8') as f:
            for line_num, line in enumerate(f, 1):
                # 去除首尾空白字符
                line = line.strip()

                # 跳过空行和注释行
                if not line or line.startswith('--'):
                    continue

                # 移除行末注释
                if '--' in line:
                    line = line.split('--')[0].strip()

                # 确保SQL语句以分号结尾
                if line and not line.endswith(';'):
                    line += ';'

                if line and line != ';':
                    sql_statements.append((line_num, line))

        print("[%s] 成功读取SQL文件: %s，共%s条有效SQL语句" % (
            datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            file_path, len(sql_statements)
        ))

    except Exception as e:
        print("[%s] 读取SQL文件失败: %s" % (
            datetime.now().strftime('%Y-%m-%d %H:%M:%S'), str(e)
        ))

    return sql_statements


class MySQLClientExecutor(object):
    def __init__(self, host, port, user, password, database, mysql_client_path='mysql'):
        """
        初始化MySQL客户端执行器
        
        Args:
            host (str): MySQL服务器地址
            port (int): MySQL端口号
            user (str): 用户名
            password (str): 密码
            database (str): 数据库名
            mysql_client_path (str): mysql客户端命令路径，默认为'mysql'
        """
        self.host = host
        self.port = port
        self.user = user
        self.password = password
        self.database = database
        self.mysql_client_path = mysql_client_path

    def test_connection(self):
        """测试MySQL连接是否正常"""
        try:
            # 构建测试连接的命令
            cmd = [
                self.mysql_client_path,
                '-h', self.host,
                '-P', str(self.port),
                '-u', self.user,
                '-p%s' % self.password,
                self.database,
                '-e', 'SELECT 1;'
            ]

            print("[%s] 测试MySQL连接..." % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

            # 执行测试命令
            process = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                shell=False
            )

            stdout, stderr = process.communicate()

            if process.returncode == 0:
                print("[%s] ✓ MySQL连接测试成功" % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
                return True
            else:
                print("[%s] ✗ MySQL连接测试失败: %s" % (
                    datetime.now().strftime('%Y-%m-%d %H:%M:%S'), stderr.strip()
                ))
                return False

        except Exception as e:
            print("[%s] ✗ 连接测试异常: %s" % (
                datetime.now().strftime('%Y-%m-%d %H:%M:%S'), str(e)
            ))
            return False

    def execute_sql(self, sql):
        """
        通过mysql客户端执行单个SQL语句
        
        Args:
            sql (str): 要执行的SQL语句
            
        Returns:
            tuple: (是否成功, 输出结果, 错误信息)
        """
        try:
            # 创建临时文件存储SQL语句
            temp_fd, temp_path = tempfile.mkstemp(suffix='.sql', text=True)

            try:
                # 写入SQL语句到临时文件
                with os.fdopen(temp_fd, 'w') as temp_file:
                    temp_file.write(sql.encode('utf-8') if isinstance(sql, unicode) else sql)

                # 构建mysql命令
                cmd = [
                    self.mysql_client_path,
                    '-h', self.host,
                    '-P', str(self.port),
                    '-u', self.user,
                    '-p%s' % self.password,
                    self.database,
                    '--default-character-set=utf8',
                    '-v',  # 显示执行的SQL语句
                    '-e', 'source %s' % temp_path
                ]

                # 执行命令
                process = subprocess.Popen(
                    cmd,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    shell=False
                )

                stdout, stderr = process.communicate()

                # 清理临时文件
                try:
                    os.unlink(temp_path)
                except:
                    pass

                if process.returncode == 0:
                    return True, stdout.strip(), stderr.strip()
                else:
                    return False, stdout.strip(), stderr.strip()

            except Exception as e:
                # 确保临时文件被清理
                try:
                    os.unlink(temp_path)
                except:
                    pass
                raise e

        except Exception as e:
            return False, "", str(e)

    def execute_sql_direct(self, sql):
        """
        直接通过mysql客户端执行SQL语句（不使用临时文件）
        
        Args:
            sql (str): 要执行的SQL语句
            
        Returns:
            tuple: (是否成功, 输出结果, 错误信息)
        """
        try:
            # 构建mysql命令，直接传递SQL语句
            cmd = [
                self.mysql_client_path,
                '-h', self.host,
                '-P', str(self.port),
                '-u', self.user,
                '-p%s' % self.password,
                self.database,
                '--default-character-set=utf8',
                '-v',  # 显示执行的SQL语句
                '-e', sql
            ]

            # 执行命令
            process = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                shell=False
            )

            stdout, stderr = process.communicate()

            if process.returncode == 0:
                return True, stdout.strip(), stderr.strip()
            else:
                return False, stdout.strip(), stderr.strip()

        except Exception as e:
            return False, "", str(e)

    def execute_sql_file(self, file_path, delay_seconds=60):
        """
        执行SQL文件中的所有语句，每个语句之间暂停指定时间
        
        Args:
            file_path (str): SQL文件路径
            delay_seconds (int): 每个SQL语句之间的延迟时间（秒），默认60秒
        """
        # 读取SQL文件
        sql_statements = read_sql_file(file_path)

        if not sql_statements:
            print("[%s] 没有找到有效的SQL语句" % (
                datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            ))
            return

        # 测试数据库连接
        if not self.test_connection():
            print("[%s] 数据库连接失败，终止执行" % (
                datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            ))
            return

        success_count = 0
        error_count = 0

        try:
            for i, (line_num, sql) in enumerate(sql_statements, 1):
                print("\n" + "=" * 80)
                print("[%s] 执行第 %s/%s 个SQL语句 (文件第%s行):" % (
                    datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    i, len(sql_statements), line_num
                ))
                print("SQL: %s" % sql)

                # 执行SQL语句
                success, stdout, stderr = self.execute_sql_direct(sql)

                if success:
                    success_count += 1
                    print("[%s] ✓ 执行成功" % (
                        datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    ))

                    # 显示输出结果
                    if stdout:
                        print("输出:")
                        print(stdout)
                    if stderr:
                        print("详细信息:")
                        print(stderr)
                else:
                    error_count += 1
                    print("[%s] ✗ 执行失败" % (
                        datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                    ))

                    if stdout:
                        print("输出:")
                        print(stdout)
                    if stderr:
                        print("错误信息:")
                        print(stderr)

                # 如果不是最后一个SQL语句，则暂停
                if i < len(sql_statements):
                    print("[%s] 等待 %s 秒后执行下一个SQL..." % (
                        datetime.now().strftime('%Y-%m-%d %H:%M:%S'), delay_seconds
                    ))
                    time.sleep(delay_seconds)

        except KeyboardInterrupt:
            print("\n[%s] 用户中断执行" % (
                datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            ))

        finally:
            # 输出执行统计
            print("\n" + "=" * 80)
            print("[%s] 执行完成统计:" % (
                datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            ))
            print("  总SQL语句数: %s" % len(sql_statements))
            print("  成功执行: %s" % success_count)
            print("  执行失败: %s" % error_count)


def main():
    """主函数"""
    # 尝试导入配置文件
    try:
        from mysql_client_config import MYSQL_CONFIG, SQL_FILE_PATH, DELAY_SECONDS
        config = MYSQL_CONFIG
        sql_file_path = SQL_FILE_PATH
        delay_seconds = DELAY_SECONDS
        print("使用配置文件: mysql_client_config.py")
    except ImportError:
        print("警告: 无法导入mysql_client_config.py配置文件，使用默认配置")
        # MySQL连接配置 - 请根据实际情况修改这些参数
        config = {
            'host': 'localhost',  # MySQL服务器地址
            'port': 3306,  # MySQL端口号
            'user': 'root',  # 用户名
            'password': 'your_password',  # 密码 - 请修改为实际密码
            'database': 'your_database',  # 数据库名 - 请修改为实际数据库名
            'mysql_client_path': 'mysql'  # mysql客户端命令路径
        }

        # SQL文件路径
        sql_file_path = '/path/to/your/sqlscript/alter_statements-第一批.sql'

        # 每个SQL语句之间的延迟时间（秒）
        delay_seconds = 60

    print("MySQL客户端SQL脚本执行器 - Python 2.7版本")
    print("=" * 60)
    print("SQL文件: %s" % sql_file_path)
    print("延迟时间: %s 秒" % delay_seconds)
    print("数据库: %s@%s:%s/%s" % (
        config['user'], config['host'], config['port'], config['database']
    ))
    print("MySQL客户端: %s" % config['mysql_client_path'])
    print("=" * 60)

    # 确认执行
    try:
        confirm = raw_input("确认执行吗？(y/N): ")
    except KeyboardInterrupt:
        print("\n用户取消执行")
        return

    if confirm.lower() != 'y':
        print("用户取消执行")
        return

    # 创建执行器并执行
    executor = MySQLClientExecutor(**config)
    executor.execute_sql_file(sql_file_path, delay_seconds)


if __name__ == '__main__':
    main()
